﻿
#include "VtkWidget.hpp"

#include <Message_Messenger.hxx>
#include <Message.hxx>

#include <vtkLogger.h>
#include <vtkLight.h>
#include <vtkLine.h>
#include <vtkTextMapper.h>
#include <vtkSphereSource.h>
#include <vtkLookupTable.h>
#include <vtkAxesActor.h>
#include <vtkBillboardTextActor3D.h>
#include <vtkPolyDataMapper.h>
#include <vtkAssembly.h>
#include <vtkProp3D.h>

#include <QMenuBar>
#include <QMouseEvent>

#include "../OL3D/ROColorScalarBar2d.hpp"
#include "../OL3D/ROBoundary3d.hpp"
#include "../OL3D/ROScaleLegend2d.hpp"
#include "../OL3D/ROAxes3d.hpp"

#include "../OLApp/Application.hpp"


namespace NSWidgets {

    VtkWidget::VtkWidget(QWidget* parent)
        : ViewWidget(parent) {
       
        setFocusPolicy(Qt::StrongFocus);
        // 设置小部件为强聚焦策略
        vtkLogger::SetStderrVerbosity(vtkLogger::VERBOSITY_OFF);
        /*悬浮菜单*/
        setMouseTracking(true);
        vtkGenericOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(8);
        QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat(true));
        m_opengl_widget = new QVTKOpenGLNativeWidget(this);
        m_opengl_widget->setMouseTracking(true);

        addWidget(m_opengl_widget);

        /*设置渲染窗口*/
        m_render_window = vtkGenericOpenGLRenderWindow::New();
        m_render_window->SetMultiSamples(8);
        m_render_window->SetLineSmoothing(true);
        m_opengl_widget->setRenderWindow(m_render_window);
        /*模型的渲染器*/
        m_renderer = vtkRenderer::New();
        m_render_window->AddRenderer(m_renderer);
        /*相机*/
        m_camera = vtkCamera::New();
        m_renderer->SetActiveCamera(m_camera);
        m_camera->UseOffAxisProjectionOff();
        m_camera->ComputeViewPlaneNormal();
        m_camera->SetParallelProjection(true);
        /*默认坐标轴*/

        colorWidgetSetup();                 /*ColorBarWidget*/
        camOrientWidgetInit();
        copyrightTextInit();                   /*显示坐标系的vtk组件 */
        /*渐变的背景*/
        m_renderer->SetBackground(0.7, 0.8, 0.9);
        //m_renderer->SetBackground2(0.2, 0.3, 0.5);
        m_renderer->SetGradientBackground(false);
        /*添加缩放条*/
        m_saclebar = NS3d::ROScaleLegend2d::New();
        m_renderer->AddViewProp(m_saclebar);

        m_axes = NS3d::ROAxes3d::New();
        m_axes->setTargetSize(_S(80));
        m_renderer->AddActor(m_axes);
        //*******************************************************************//
        //Sp(NS3d::ROBoundary3d) bd = NS3d::ROBoundary3d::New();
        //vtkNew<vtkPoints> points;
        //double p1[3] = { 80,0, 0 };
        //points->InsertNextPoint(p1);
        //bd->setPostion(p1[0], p1[1], p1[2]);
        //bd->setFixedPoints(points);
        //bd->setTargetSize(8);
        //bd->Build();
        //m_renderer->AddActor(bd);
       //*******************************************************************//
        //#define FXAA
#ifdef FXAA
    /*其他设置*/
        renderer->SetUseFXAA(true);
#endif // FXAA

#ifdef DEPTHPEELING
        renderer->UseDepthPeelingOn();
        renderer->UseDepthPeelingForVolumesOn();
#endif // DEPTHPEELING
        /*三项在其他电脑上运行会有显示的问题-慎用*/
        m_renderer->ResetCamera();
        m_render_window->Render();

    }


    void VtkWidget::createDefaultLight() {
        auto default_light = vtkLight::New();
        default_light->SetColor(1, 1, 1);
        default_light->SetLightTypeToCameraLight();
        default_light->SetFocalPoint(m_renderer->GetActiveCamera()->GetFocalPoint());
        m_renderer->RemoveAllLights();
        m_renderer->AddLight(default_light);
        m_renderer->SetLightFollowCamera(true);
        // 增强灯光强度
        default_light->SetIntensity(1.5);
        default_light->SwitchOn();

        m_render_window->Render();
    }


    void VtkWidget::createDefaultGrid(double sketch_size, int direction) {
        // 创建平面源，这将生成一个平面网格
        vtkNew<vtkPlaneSource> grid_source;
        grid_source->SetCenter(0.0, 0.0, 0.0); 
        grid_source->SetResolution(40, 40);
        if (0 <= direction && direction <= 1) {
            grid_source->SetNormal(0.0, 0.0, 1.0); 
            grid_source->SetOrigin(-sketch_size / 2, -sketch_size / 2, 0);
            grid_source->SetPoint1(sketch_size / 2, -sketch_size / 2, 0);
            grid_source->SetPoint2(-sketch_size / 2, sketch_size / 2, 0);
        }
        else if (2 <= direction && direction <= 3) {
            grid_source->SetNormal(1.0, 0.0, 0.0);
            grid_source->SetOrigin(0, -sketch_size / 2, -sketch_size / 2);
            grid_source->SetPoint1(0, sketch_size / 2, -sketch_size / 2);
            grid_source->SetPoint2(0, -sketch_size / 2, sketch_size / 2);
        }
        else if (4 <=  direction && direction <= 5) {
            grid_source->SetNormal(0.0, 1.0, 0.0);
            grid_source->SetOrigin(-sketch_size / 2, 0, -sketch_size / 2);
            grid_source->SetPoint1(sketch_size / 2, 0, -sketch_size / 2);
            grid_source->SetPoint2(-sketch_size / 2, 0, sketch_size / 2);
        } 
        // 创建映射器
        vtkNew<vtkPolyDataMapper> mapper;
        mapper->SetInputConnection(grid_source->GetOutputPort());
        // 创建演员
        vtkNew<vtkAssembly> grid_assembly;
        vtkNew<vtkActor> grid_actor;
        grid_actor->SetMapper(mapper);
        // 设置网格属性
        grid_actor->GetProperty()->SetColor(0, 0, 0);
        grid_actor->GetProperty()->SetLineWidth(2.0);
        grid_actor->GetProperty()->SetRepresentationToWireframe();
        grid_assembly->AddPart(grid_actor);

        vtkNew<vtkLineSource> x_axis;
        x_axis->SetPoint1(-sketch_size / 2, 0, 0.01); 
        x_axis->SetPoint2(sketch_size / 2, 0, 0.01);
        vtkNew<vtkPolyDataMapper> x_axis_mapper;
        x_axis_mapper->SetInputConnection(x_axis->GetOutputPort()); 
        vtkNew<vtkActor> x_axis_actor;
        x_axis_actor->SetMapper(x_axis_mapper);
        x_axis_actor->GetProperty()->SetColor(0, 0, 1);
        x_axis_actor->GetProperty()->SetLineWidth(3.0);
        grid_assembly->AddPart(x_axis_actor);

        // 添加Y轴（双点划线）
        vtkNew<vtkLineSource> y_axis;
        y_axis->SetPoint1(0, -sketch_size / 2, 0.01); 
        y_axis->SetPoint2(0, sketch_size / 2, 0.01);
        vtkNew<vtkPolyDataMapper> y_axis_mapper;
        y_axis_mapper->SetInputConnection(y_axis->GetOutputPort());
        vtkNew<vtkActor> y_axis_actor;
        y_axis_actor->SetMapper(y_axis_mapper);
        y_axis_actor->GetProperty()->SetColor(0, 0, 1);
        y_axis_actor->GetProperty()->SetLineWidth(3.0);
        grid_assembly->AddPart(y_axis_actor);
        m_sketch_grid = grid_assembly;

        m_renderer->AddActor(grid_assembly);
    }


    void VtkWidget::paintEvent(QPaintEvent* event) {

        QWidget::paintEvent(event);

    }



    void VtkWidget::mouseMoveEvent(QMouseEvent* event) {


        QWidget::mouseMoveEvent(event);
    }



    void VtkWidget::mouseReleaseEvent(QMouseEvent* event) {
        /*取消高亮的物体(用户自己取消)*/
        //if (m_hightlight && event->button() != Qt::MiddleButton) {
        //    m_renderer->RemoveActor(m_hightlight);
        //}
        //m_renderer->Render();
        //m_render_window->Render();

        QWidget::mouseReleaseEvent(event);
    }



    void VtkWidget::mousePressEvent(QMouseEvent* event) {
        int pos[2];
        pos[0] = event->pos().x();
        pos[1] = abs(height() - event->pos().y());
        if (event->button() == Qt::LeftButton) {

        }

        QWidget::mousePressEvent(event);
    }


    void VtkWidget::closeEvent(QCloseEvent* event) {


        QWidget::closeEvent(event);
    }



    void VtkWidget::copyrightTextInit() {
        vtkNew<vtkTextMapper> mapper;
        /*Software*/
        mapper->SetInput("OpenLaser v25");
        mapper->GetTextProperty()->SetVerticalJustificationToTop();
        mapper->GetTextProperty()->SetFontFamilyToArial();
        mapper->GetTextProperty()->SetColor(0.2, 0.2, 0.2);
        mapper->GetTextProperty()->SetFontSize(26);
        mapper->GetTextProperty()->SetBold(true);
        vtkNew<vtkActor2D> info;
        info->SetMapper(mapper);
        info->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
        info->GetPositionCoordinate()->SetValue(0.02, 0.98);
        //info_actors.push_back(info);
        m_renderer->AddActor2D(info);

        auto  _mapper = vtkTextMapper::New();
        // 提示信息
        _mapper->SetInput("©Copyright 2025 KONG CHUIJIANG.");
        _mapper->GetTextProperty()->SetVerticalJustificationToBottom();
        _mapper->GetTextProperty()->SetFontFamilyToArial();
        _mapper->GetTextProperty()->SetColor(0.2, 0.2, 0.2);
        _mapper->GetTextProperty()->SetFontSize(15);
        vtkNew<vtkActor2D> version_info;
        version_info->SetMapper(_mapper);
        version_info->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
        version_info->GetPositionCoordinate()->SetValue(0.02, 0.02);
        //info_actors.push_back(version_info);
        m_renderer->AddActor2D(version_info);

    }



    void VtkWidget::camOrientWidgetInit() {
        m_camera_widget = vtkCameraOrientationWidget::New();
        m_camera_widget->SetParentRenderer(m_renderer);
        m_camera_widget->SetInteractor(m_render_window->GetInteractor());
        m_camera_widget->SetAnimate(true);
        m_camera_widget->AnimateOn();
        m_camera_widget->SetAnimatorTotalFrames(20);

        m_camera_widget->EnabledOn();

    }



    void VtkWidget::colorWidgetSetup() {
        m_scalarbar = NS3d::ROColorScalarBar2d::New();
        const auto& color_lut = vtkLookupTable::New();
        //设置颜色映射的数目
        color_lut->SetNumberOfTableValues(14);
        color_lut->SetHueRange(0.67, 0.0);      //色调范围从红色到蓝色
        //设置颜色映射的范围
        color_lut->SetTableRange(0, 100);
        color_lut->SetAnnotation(0.0, "Min");
        color_lut->SetAnnotation(50, "Half");
        color_lut->SetAnnotation(100, "Max");

        color_lut->Build();

        m_scalarbar->SetLookupTable(color_lut);
        m_scalarbar->SetTitle("Mises (MPa)\nAverage 75%\n");
        m_scalarbar->SetVisibility(true);
        //scalar_bar->SetPosition2(0.95, 0.85);
        m_renderer->AddActor2D(m_scalarbar);
        
    }



    VtkWidget::~VtkWidget() {
        if (m_opengl_widget != nullptr) delete m_opengl_widget;

    }


    void VtkWidget::addModels(QList<Sp(vtkProp3D)> parts, bool update) {
        for (auto& part : parts) {
            addModel(part, update);
        }
    }

    void VtkWidget::addModel(Sp(vtkProp3D) part, bool update) {
        m_renderer->AddActor(part);
        //m_area_picker->AddPickList(actor);
        /*渲染*/
        if (update) {
            m_renderer->ResetCamera();
        }
        m_renderer->Render();
        m_render_window->Render();

    }

    void VtkWidget::removeModels(QList<Sp(vtkProp3D)> parts, bool update) {
        for (auto& part : parts) {
            removeModel(part, update);
        }
    }

    void VtkWidget::removeModel(Sp(vtkProp3D) actor, bool update) {
        m_renderer->RemoveActor(actor);
        //m_area_picker->DeletePickList(actor);
        /*渲染*/
        if (update) {
            m_renderer->ResetCamera();
        }
        m_renderer->Render();
        m_render_window->Render();
    }


    void VtkWidget::changeRenderBackgroundSlot() {
        static int background_id = (background_id + 1) % 3;
        if (background_id == 0) {
            /*渐变的背景*/
            m_renderer->SetBackground(0.8, 0.8, 1.0);
            m_renderer->SetBackground2(0.2, 0.4, 0.6);
            m_renderer->SetGradientBackground(true);
        }
        else if (background_id == 1) {
            m_renderer->SetBackground(1, 1, 1);
            m_renderer->SetGradientBackground(false);
        }
        else {
            m_renderer->SetBackground(0, 0, 0);
            m_renderer->SetGradientBackground(false);
        }
        m_render_window->Render();

    }


    void VtkWidget::Render() {
        m_renderer->Render();
        m_render_window->Render();

    }

    int VtkWidget::getRenderedCount() {
        int count = m_renderer->GetNumberOfPropsRendered();
        return count;
    }

    void VtkWidget::setViewDirection(int index) {
        /*index : 0-xoy 1-yox 2-yoz 3-zoy 4-zox 5-xoz 6-xyz*/
        if (m_camera == nullptr)return;
        m_camera->SetFocalPoint(0, 0, 0);
        switch (index) {
        case 0:
            m_camera->SetPosition(0, 0, -1);
            m_camera->SetViewUp(0, 1, 0);
            break;
        case 1:
            m_camera->SetPosition(0, 0, 1);
            m_camera->SetViewUp(0, 1, 0);
            break;
        case 2:
            m_camera->SetPosition(-1, 0, 0);
            m_camera->SetViewUp(0, 0, 1);

            break;
        case 3:
            m_camera->SetPosition(1, 0, 0);
            m_camera->SetViewUp(0, 0, 1);
            break;
        case 4:
            m_camera->SetPosition(0, -1, 0);
            m_camera->SetViewUp(0, 0, 1);
            break;
        case 5:
            m_camera->SetPosition(0, 1, 0);
            m_camera->SetViewUp(0, 0, 1);
            break;
        case 6:
            m_camera->SetPosition(1, 1, 1);
            m_camera->SetViewUp(0, 0, 1);
            break;
        default:
            break;
        }
        m_renderer->ResetCamera();
        m_render_window->Render();

    }

    void VtkWidget::setSelectMode(int mode) {
        vtkInteractorObserver* abs_style = m_render_window->GetInteractor()->GetInteractorStyle();
        NS3d::InteractorDefaultStyle* style = dynamic_cast<NS3d::InteractorDefaultStyle*>(abs_style);
        if (style) {
            style->setSelectMode(mode);
        }
    }

    int VtkWidget::getSelectMode() {
        vtkInteractorObserver* abs_style = m_render_window->GetInteractor()->GetInteractorStyle();
        NS3d::InteractorDefaultStyle* style = dynamic_cast<NS3d::InteractorDefaultStyle*>(abs_style);
        if (style) {
            return style->getSelectMode();
        }
        return -1;
    }

    void VtkWidget::setExInteractorStyle(NS3d::InteractorDefaultStyle* style) {
        if (style) {
            style->SetDefaultRenderer(m_renderer);
            m_render_window->GetInteractor()->SetInteractorStyle(style);
            m_intstyle = style;//只保存默认交互器

        }

    }

    void VtkWidget::setViewPerspective(bool on) {
        m_camera->SetParallelProjection(on);
        m_render_window->Render();
    }

    void VtkWidget::setViewAdapt() {
        m_renderer->ResetCamera();
        m_render_window->Render();
    }

    void VtkWidget::setViewMagnify() { 
        m_camera->Zoom(1.2);
        m_renderer->ResetCameraClippingRange(); 
        m_render_window->Render();
    }

    void VtkWidget::setViewShrink() {
        m_camera->Zoom(0.8);
        m_renderer->ResetCameraClippingRange();
        m_render_window->Render();
    }

    /**
    *设置草绘模式
    */
    void VtkWidget::setSketchMode(bool sketch, int direction) {
        auto int_style = NS3d::InteractorDefaultStyle::SafeDownCast(m_intstyle);
        int_style->setSketchMode(sketch, direction); 
        setDisplayScalebar(!sketch);
        setDisplayScalarbar(!sketch);
        if (!sketch && m_sketch_grid) {
            m_renderer->RemoveActor(m_sketch_grid);
            setViewDirection(6); 
        }
        else {
            createDefaultGrid(400, direction);
            int_style->setSketchPrecision(400 / 40 / 5);
            m_camera->ParallelProjectionOn();
            setViewDirection(direction);//1-3-5方向 
        }

    }

    void VtkWidget::setDisplayNode(bool display) {

        Render();
    }

    void VtkWidget::setDisplayMesh(bool display) {

        Render();
    }

    void VtkWidget::setDisplayEdge(bool display) {

        Render();
    }

    void VtkWidget::setDisplaySolid(bool display) {

        Render();
    }

    void VtkWidget::setDisplayScalarbar(bool display) {
        m_scalarbar->SetVisibility(display);
        Render();
    }

    void VtkWidget::setDisplayScalebar(bool display) {
        m_saclebar->SetVisibility(display);
        Render();
    }

}

